﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Z.IconLibraryGenerator.WinForm
{
    public class ProjectSettings : Page
    {
        #region Designer

        /// <summary>The menu bar.</summary>
        public MenuBar MenuBar;

        /// <summary>The web browser control.</summary>
        public WebBrowser uiWebBrowser;

        #region Step1

        /// <summary>Pathname of the destination directory.</summary>
        public HtmlElement uiDestinationDirectory;

        /// <summary>Destination directory browse.</summary>
        public HtmlElement uiDestinationDirectoryBrowse;

        /// <summary>Destination directory label.</summary>
        public HtmlElement uiDestinationDirectoryLabel;

        /// <summary>The framework net 20 option.</summary>
        public HtmlElement uiFrameworkNet20Option;

        /// <summary>The framework net 35 option.</summary>
        public HtmlElement uiFrameworkNet35Option;

        /// <summary>Name of the project.</summary>
        public HtmlElement uiProjectName;

        /// <summary>The project name label.</summary>
        public HtmlElement uiProjectNameLabel;

        /// <summary>The project namespace.</summary>
        public HtmlElement uiProjectNamespace;

        /// <summary>The project namespace label.</summary>
        public HtmlElement uiProjectNamespaceLabel;

        #endregion

        #region Step2

        /// <summary>Sets the add icon belongs to.</summary>
        public HtmlElement uiAddIconSets;

        /// <summary>Full pathname of the error invalid icon file.</summary>
        public HtmlElement uiErrorInvalidIconPath;

        /// <summary>The error invalid icon prefix.</summary>
        public HtmlElement uiErrorInvalidIconPrefix;

        /// <summary>Full pathname of the error mandatory icon file.</summary>
        public HtmlElement uiErrorMandatoryIconPath;

        /// <summary>The error mandatory icon prefix.</summary>
        public HtmlElement uiErrorMandatoryIconPrefix;

        /// <summary>The second user interface error step.</summary>
        public HtmlElement uiErrorStep2;

        /// <summary>Full pathname of the icon file.</summary>
        public HtmlElement uiIconPath;

        /// <summary>The icon path browse.</summary>
        public HtmlElement uiIconPathBrowse;

        /// <summary>The icon path label.</summary>
        public HtmlElement uiIconPathLabel;

        /// <summary>The icon prefix.</summary>
        public HtmlElement uiIconPrefix;

        /// <summary>The icon prefix label.</summary>
        public HtmlElement uiIconPrefixLabel;

        /// <summary>The icon sets table.</summary>
        public HtmlElement uiIconSetsTable;

        #endregion

        #region Step3

        /// <summary>The error.</summary>
        public HtmlElement uiError;

        /// <summary>Pathname of the error invalid destination directory.</summary>
        public HtmlElement uiErrorInvalidDestinationDirectory;

        /// <summary>Full pathname of the error invalid icon set file.</summary>
        public HtmlElement uiErrorInvalidIconSetPath;

        /// <summary>Name of the error invalid project.</summary>
        public HtmlElement uiErrorInvalidProjectName;

        /// <summary>The error invalid project namespace.</summary>
        public HtmlElement uiErrorInvalidProjectNamespace;

        /// <summary>Pathname of the error mandatory destination directory.</summary>
        public HtmlElement uiErrorMandatoryDestinationDirectory;

        /// <summary>Sets the error mandatory icon belongs to.</summary>
        public HtmlElement uiErrorMandatoryIconSets;

        /// <summary>Name of the error mandatory project.</summary>
        public HtmlElement uiErrorMandatoryProjectName;

        /// <summary>The error mandatory project namespace.</summary>
        public HtmlElement uiErrorMandatoryProjectNamespace;

        /// <summary>The project generate.</summary>
        public HtmlElement uiProjectGenerate;

        #endregion

        #endregion

        /// <summary>Constructor.</summary>
        /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
        /// <param name="webBrowser">The web browser control.</param>
        public ProjectSettings(WebBrowser webBrowser)
        {
            try
            {
                MenuBar = new MenuBar(webBrowser);

                uiWebBrowser = webBrowser;

                if (uiWebBrowser.Document == null)
                {
                    throw new Exception("Document cannot be null.");
                }

                // STEP 1
                {
                    uiProjectNameLabel = uiWebBrowser.Document.GetElementById("uiProjectNameLabel");
                    uiProjectName = uiWebBrowser.Document.GetElementById("uiProjectName");
                    uiProjectNamespaceLabel = uiWebBrowser.Document.GetElementById("uiProjectNamespaceLabel");
                    uiProjectNamespace = uiWebBrowser.Document.GetElementById("uiProjectNamespace");
                    uiFrameworkNet35Option = uiWebBrowser.Document.GetElementById("uiFrameworkNet35Option");
                    uiFrameworkNet20Option = uiWebBrowser.Document.GetElementById("uiFrameworkNet20Option");
                    uiDestinationDirectoryLabel = uiWebBrowser.Document.GetElementById("uiDestinationDirectoryLabel");
                    uiDestinationDirectory = uiWebBrowser.Document.GetElementById("uiDestinationDirectory");
                    uiDestinationDirectoryBrowse = uiWebBrowser.Document.GetElementById("uiDestinationDirectoryBrowse");
                }

                // STEP 2
                {
                    uiErrorStep2 = uiWebBrowser.Document.GetElementById("uiErrorStep2");
                    uiErrorMandatoryIconPrefix = uiWebBrowser.Document.GetElementById("uiErrorMandatoryIconPrefix");
                    uiErrorMandatoryIconPath = uiWebBrowser.Document.GetElementById("uiErrorMandatoryIconPath");
                    uiErrorInvalidIconPrefix = uiWebBrowser.Document.GetElementById("uiErrorInvalidIconPrefix");
                    uiErrorInvalidIconPath = uiWebBrowser.Document.GetElementById("uiErrorInvalidIconPath");
                    uiIconPrefixLabel = uiWebBrowser.Document.GetElementById("uiIconPrefixLabel");
                    uiIconPrefix = uiWebBrowser.Document.GetElementById("uiIconPrefix");
                    uiIconPathLabel = uiWebBrowser.Document.GetElementById("uiIconPathLabel");
                    uiIconPath = uiWebBrowser.Document.GetElementById("uiIconPath");
                    uiIconSetsTable = uiWebBrowser.Document.GetElementById("uiIconSetsTable");
                    uiIconPathBrowse = uiWebBrowser.Document.GetElementById("uiIconPathBrowse");
                    uiAddIconSets = uiWebBrowser.Document.GetElementById("uiAddIconSets");
                }

                // STEP 3
                {
                    uiError = uiWebBrowser.Document.GetElementById("uiError");
                    uiErrorMandatoryProjectName = uiWebBrowser.Document.GetElementById("uiErrorMandatoryProjectName");
                    uiErrorMandatoryProjectNamespace = uiWebBrowser.Document.GetElementById("uiErrorMandatoryProjectNamespace");
                    uiErrorInvalidProjectName = uiWebBrowser.Document.GetElementById("uiErrorInvalidProjectName");
                    uiErrorInvalidProjectNamespace = uiWebBrowser.Document.GetElementById("uiErrorInvalidProjectNamespace");
                    uiErrorMandatoryIconSets = uiWebBrowser.Document.GetElementById("uiErrorMandatoryIconSets");
                    uiErrorInvalidIconSetPath = uiWebBrowser.Document.GetElementById("uiErrorInvalidIconSetPath");
                    uiErrorMandatoryDestinationDirectory = uiWebBrowser.Document.GetElementById("uiErrorMandatoryDestinationDirectory");
                    uiErrorInvalidDestinationDirectory = uiWebBrowser.Document.GetElementById("uiErrorInvalidDestinationDirectory");
                    uiProjectGenerate = uiWebBrowser.Document.GetElementById("uiProjectGenerate");
                }

                LoadValues();
                BindEvents();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, @"General Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>Loads the values.</summary>
        public void LoadValues()
        {
            if (!string.IsNullOrEmpty(My.CurrentProject.SaveFile))
            {
                uiProjectName.SetValue(My.CurrentProject.ProjectName);
                uiProjectNamespace.SetValue(My.CurrentProject.ProjectNamespace);
                My.ApplicationConfiguration.ProjectPath = My.CurrentProject.DestinationDirectory;
                uiDestinationDirectory.SetValue(My.CurrentProject.DestinationDirectory);

                uiFrameworkNet20Option.SetChecked(My.CurrentProject.Framework == ProjectFrameworkType.Framework20);
                uiFrameworkNet20Option.SetChecked(My.CurrentProject.Framework == ProjectFrameworkType.Framework35);

                foreach (ProjectIcon icon in My.CurrentProject.Icons)
                {
                    AddIconRow(icon.Prefix, icon.Path);
                }
            }
        }

        /// <summary>Bind events.</summary>
        public void BindEvents()
        {
            uiAddIconSets.Click += AddIconSets_OnClick;
            uiIconPathBrowse.Click += uiIconPathBrowse_OnClick;
            uiDestinationDirectoryBrowse.Click += uiDestinationDirectoryBrowse_OnClick;
            uiProjectGenerate.Click += ProjectGenerate_OnClick;
        }

        /// <summary>Event handler. Called by uiDestinationDirectoryBrowse for on click events.</summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">HTML element event information.</param>
        public void uiDestinationDirectoryBrowse_OnClick(object sender, HtmlElementEventArgs e)
        {
            var dialog = new FolderBrowserDialog
            {
                Description = @"Choose your destination directory.",
                SelectedPath = My.ApplicationConfiguration.ProjectPath ?? string.Empty
            };

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                string path = dialog.SelectedPath;
                My.ApplicationConfiguration.ProjectPath = path;
                uiDestinationDirectory.SetValue(path);
            }
        }

        /// <summary>Event handler. Called by uiIconPathBrowse for on click events.</summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">HTML element event information.</param>
        public void uiIconPathBrowse_OnClick(object sender, HtmlElementEventArgs e)
        {
            var dialog = new FolderBrowserDialog
            {
                Description = @"Choose the directory with your icons.",
                SelectedPath = My.ApplicationConfiguration.IconSetPath ?? string.Empty
            };

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                string path = dialog.SelectedPath;
                My.ApplicationConfiguration.IconSetPath = path;
                uiIconPath.SetValue(path);
            }
        }

        /// <summary>Event handler. Called by ProjectGenerate for on click events.</summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">HTML element event information.</param>
        public void ProjectGenerate_OnClick(object sender, HtmlElementEventArgs e)
        {
            ResetErrorCss();
            TrimValue();

            if (ProjectGenerate_IsValid())
            {
                My.CurrentProject.ProjectName = uiProjectName.GetValue();
                My.CurrentProject.ProjectNamespace = uiProjectNamespace.GetValue();
                My.CurrentProject.DestinationDirectory = uiDestinationDirectory.GetValue();
                My.CurrentProject.Framework = uiFrameworkNet35Option.GetChecked() ?
                    ProjectFrameworkType.Framework35 :
                    ProjectFrameworkType.Framework20;

                My.CurrentProject.Icons = new List<ProjectIcon>();

                HtmlElementCollection rows = uiIconSetsTable.GetRows();
                for (int i = 1; i < rows.Count; i++)
                {
                    HtmlElement row = rows[i];
                    My.CurrentProject.Icons.Add(new ProjectIcon(row.Children[0].InnerHtml, row.Children[1].InnerHtml));
                }

                if (My.CurrentProject.Save())
                {
                    My.ApplicationConfiguration.SaveProject(My.CurrentProject);
                    IconLibraryGeneratorManager.Execute(My.CurrentProject);
                }
            }
        }

        /// <summary>Determines if we can project generate is valid.</summary>
        /// <returns>true if it succeeds, false if it fails.</returns>
        public bool ProjectGenerate_IsValid()
        {
            bool isValid = true;

            if (string.IsNullOrEmpty(uiProjectName.GetValue()))
            {
                uiProjectNameLabel.SetCssClass(uiProjectNameLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorMandatoryProjectName.SetCssClass(uiErrorMandatoryProjectName.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }
            else if (uiProjectName.GetValue().Contains(" "))
            {
                uiProjectNameLabel.SetCssClass(uiProjectNameLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorInvalidProjectName.SetCssClass(uiErrorInvalidProjectName.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }

            if (string.IsNullOrEmpty(uiProjectNamespace.GetValue()))
            {
                uiProjectNamespaceLabel.SetCssClass(uiProjectNamespaceLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorMandatoryProjectNamespace.SetCssClass(uiErrorMandatoryProjectNamespace.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }
            else if (uiProjectNamespace.GetValue().Contains(" "))
            {
                uiProjectNamespaceLabel.SetCssClass(uiProjectNamespaceLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorInvalidProjectNamespace.SetCssClass(uiErrorInvalidProjectNamespace.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }

            if (string.IsNullOrEmpty(uiDestinationDirectory.GetValue()))
            {
                uiDestinationDirectoryLabel.SetCssClass(uiProjectNamespaceLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorMandatoryDestinationDirectory.SetCssClass(uiErrorMandatoryProjectNamespace.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }
            else if (!uiDestinationDirectory.GetValue().ToDirectoryInfo().Exists)
            {
                uiDestinationDirectoryLabel.SetCssClass(uiProjectNamespaceLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorInvalidDestinationDirectory.SetCssClass(uiErrorInvalidProjectNamespace.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }

            if (uiIconSetsTable.RowLength() <= 1)
            {
                uiErrorMandatoryIconSets.SetCssClass(uiErrorMandatoryIconSets.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }
            else
            {
                HtmlElementCollection rows = uiIconSetsTable.GetRows();
                for (int i = 1; i < rows.Count; i++)
                {
                    HtmlElement row = rows[i];

                    string directory = row.Children[1].InnerHtml;
                    if (!directory.ToDirectoryInfo().Exists)
                    {
                        uiErrorMandatoryIconSets.SetCssClass(uiErrorMandatoryIconSets.GetCssClass().Replace(" valid", " error"));
                        isValid = false;
                    }
                }
            }

            if (!isValid)
            {
                uiError.SetCssClass(uiError.GetCssClass().Replace(" valid", " error"));
            }

            return isValid;
        }


        /// <summary>Trim value.</summary>
        public void TrimValue()
        {
            if (!string.IsNullOrEmpty(uiProjectName.GetValue()))
            {
                uiProjectName.SetValue(uiProjectName.GetValue().Trim());
            }
            if (!string.IsNullOrEmpty(uiProjectNamespace.GetValue()))
            {
                uiProjectNamespace.SetValue(uiProjectNamespace.GetValue().Trim());
            }
            if (!string.IsNullOrEmpty(uiIconPrefix.GetValue()))
            {
                uiIconPrefix.SetValue(uiIconPrefix.GetValue().Trim());
            }
        }

        /// <summary>Resets the error CSS.</summary>
        public void ResetErrorCss()
        {
            // STEP 1
            uiProjectNameLabel.SetCssClass(uiProjectNameLabel.GetCssClass().Replace(" error", " valid"));
            uiProjectNamespaceLabel.SetCssClass(uiProjectNamespaceLabel.GetCssClass().Replace(" error", " valid"));
            uiDestinationDirectoryLabel.SetCssClass(uiDestinationDirectoryLabel.GetCssClass().Replace(" error", " valid"));

            // STEP 2
            uiErrorStep2.SetCssClass(uiErrorStep2.GetCssClass().Replace(" error", " valid"));
            uiErrorMandatoryIconPrefix.SetCssClass(uiErrorMandatoryIconPrefix.GetCssClass().Replace(" error", " valid"));
            uiErrorInvalidIconPrefix.SetCssClass(uiErrorInvalidIconPrefix.GetCssClass().Replace(" error", " valid"));
            uiErrorMandatoryIconPath.SetCssClass(uiErrorMandatoryIconPath.GetCssClass().Replace(" error", " valid"));
            uiErrorInvalidIconPath.SetCssClass(uiErrorInvalidIconPath.GetCssClass().Replace(" error", " valid"));

            uiIconPrefixLabel.SetCssClass(uiIconPrefixLabel.GetCssClass().Replace(" error", " valid"));
            uiIconPathLabel.SetCssClass(uiIconPathLabel.GetCssClass().Replace(" error", " valid"));

            // STEP 3
            uiError.SetCssClass(uiError.GetCssClass().Replace(" error", " valid"));
            uiErrorMandatoryProjectName.SetCssClass(uiErrorMandatoryProjectName.GetCssClass().Replace(" error", " valid"));
            uiErrorMandatoryProjectNamespace.SetCssClass(uiErrorMandatoryProjectNamespace.GetCssClass().Replace(" error", " valid"));
            uiErrorMandatoryDestinationDirectory.SetCssClass(uiErrorMandatoryDestinationDirectory.GetCssClass().Replace(" error", " valid"));
            uiErrorMandatoryIconSets.SetCssClass(uiErrorMandatoryIconSets.GetCssClass().Replace(" error", " valid"));
            uiErrorInvalidProjectName.SetCssClass(uiErrorInvalidProjectName.GetCssClass().Replace(" error", " valid"));
            uiErrorInvalidProjectNamespace.SetCssClass(uiErrorInvalidProjectNamespace.GetCssClass().Replace(" error", " valid"));
            uiErrorInvalidIconSetPath.SetCssClass(uiErrorInvalidIconSetPath.GetCssClass().Replace(" error", " valid"));
            uiErrorInvalidDestinationDirectory.SetCssClass(uiErrorInvalidDestinationDirectory.GetCssClass().Replace(" error", " valid"));
        }

        #region Icon

        /// <summary>Event handler. Called by AddIconSets for on click events.</summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">HTML element event information.</param>
        public void AddIconSets_OnClick(object sender, HtmlElementEventArgs e)
        {
            ResetErrorCss();

            if (AddIconsSets_IsValid())
            {
                AddIconRow(uiIconPrefix.GetValue(), uiIconPath.GetValue());
            }
        }

        /// <summary>Adds an icon row to 'path'.</summary>
        /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
        /// <param name="prefix">The prefix.</param>
        /// <param name="path">Full pathname of the file.</param>
        public void AddIconRow(string prefix, string path)
        {
            HtmlElement row = uiIconSetsTable.InsertRow();
            HtmlElement cell1 = row.InsertCell();
            HtmlElement cell2 = row.InsertCell();
            HtmlElement cell3 = row.InsertCell();

            cell1.InnerText = prefix;
            cell2.InnerText = path;
            cell3.InnerHtml = "<button id='uiIconPathBrowse' class='btn btn-default'><span class='glyphicon glyphicon-remove'></span>&nbsp;&nbsp;Remove</button>";

            HtmlElement removeRow = cell3.FirstChild;

            if (removeRow == null)
            {
                throw new Exception("Failed to create button.");
            }

            removeRow.Click += RemoveRow_Click;
        }

        /// <summary>Event handler. Called by RemoveRow for click events.</summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">HTML element event information.</param>
        private void RemoveRow_Click(object sender, HtmlElementEventArgs e)
        {
            // ReSharper disable PossibleNullReferenceException
            HtmlElement tr = ((HtmlElement) sender).Parent.Parent;
            // ReSharper restore PossibleNullReferenceException
            uiIconSetsTable.InnerHtml = uiIconSetsTable.OuterHtml.Replace(tr.OuterHtml, "");
        }


        /// <summary>Adds icons sets is valid.</summary>
        /// <returns>true if it succeeds, false if it fails.</returns>
        public bool AddIconsSets_IsValid()
        {
            bool isValid = true;

            if (string.IsNullOrEmpty(uiIconPrefix.GetValue()))
            {
                uiIconPrefixLabel.SetCssClass(uiIconPrefixLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorMandatoryIconPrefix.SetCssClass(uiErrorMandatoryIconPrefix.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }
            else if (uiIconPrefix.GetValue().Contains(" "))
            {
                uiIconPrefixLabel.SetCssClass(uiIconPrefixLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorInvalidIconPrefix.SetCssClass(uiErrorInvalidIconPrefix.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }

            if (string.IsNullOrEmpty(uiIconPath.GetValue()))
            {
                uiIconPathLabel.SetCssClass(uiIconPathLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorMandatoryIconPath.SetCssClass(uiErrorMandatoryIconPath.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }
            else if (uiIconPath.GetValue().Contains(" "))
            {
                uiIconPathLabel.SetCssClass(uiIconPathLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorInvalidIconPath.SetCssClass(uiErrorInvalidIconPath.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }
            else if (!uiIconPath.GetValue().ToDirectoryInfo().Exists)
            {
                uiIconPathLabel.SetCssClass(uiIconPathLabel.GetCssClass().Replace(" valid", " error"));
                uiErrorInvalidIconPath.SetCssClass(uiErrorInvalidIconPath.GetCssClass().Replace(" valid", " error"));
                isValid = false;
            }

            if (!isValid)
            {
                uiErrorStep2.SetCssClass(uiError.GetCssClass().Replace(" valid", " error"));
            }

            return isValid;
        }

        #endregion
    }
}